﻿/*
* This file is part of WinMergeFS.
*
* WinMergeFS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.

* WinMergeFS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WinMergeFS.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Dokan;
using WinMergeFS.Common;
using RealtimeTrace;

namespace WinMergeFS.API
{
    /// <summary>
    /// Provides main interface for control applications.
    /// </summary>
    /// 

    public class WinMergeFS
    {

        #region RealtimeTrace

        /// <summary>
        /// Use this method to initialize the RealTimeTrace.
        /// This method should be called within the class constructor(s) 
        /// if you want to override the default RealtimeTrace configuration.
        /// </summary>
        private void InitializeRealTimeTrace()
        {
            this.RealTimeTraceProvider = DataProviderType.LogFile;
            this.PreferredDumpType = DumpType.XML;
        }

        private DataProviderType _RealTimeTraceProvider = DataProviderType.LogFile;
        /// <summary>
        /// Gets or Sets the Data Store provider for the RealTimeTrace.
        /// The default Data Storage provider is a raw text file.
        /// For Windows application, this raw text file is stored at the same level of the running executable.
        /// For ASP.NET application, this raw text file is stored at the same level of the aspx page.
        /// For UI Components, this raw text file is stored in the "My Documents" user folder.
        /// By default the name of the log file is *RealtimeTrace.log*
        /// </summary>
        public DataProviderType RealTimeTraceProvider
        {
            get
            {
                return this._RealTimeTraceProvider;
            }
            set
            {
                this._RealTimeTraceProvider = value;
            }
        }

        private DumpType _PreferredDumpType = DumpType.XML;
        /// <summary>
        /// Gets or Sets the type of dump for the current class.
        /// </summary>
        public DumpType PreferredDumpType
        {
            get
            {
                return this._PreferredDumpType;
            }
            set
            {
                this._PreferredDumpType = value;
            }
        }

        private bool _HasErrors = false;
        /// <summary>
        /// Checks if an error has occured within this class instance.
        /// The Itraceable implementer should only read this property.
        /// This property is set only by the RealtimeTrace layer.
        /// </summary>
        public bool HasErrors
        {
            get { return this._HasErrors; }
            set { this._HasErrors = value; }
        }

        private System.String _LastError = System.String.Empty;
        /// <summary>
        /// Gets the last known error from the last call of a public/private member within this class instance.
        /// The Itraceable implementer should only read this property.
        /// This property is set only by the RealtimeTrace layer.
        /// </summary>
        public string LastError
        {
            get { return this._LastError; }
            set
            {
                if (value == null)
                {
                    value = System.String.Empty;
                }
                this._LastError = value;
            }
        }

        private System.String _Errors = System.String.Empty;
        /// <summary>
        /// Gets all errors from the last call of a public member within this class instance.
        /// The Itraceable implementer should only read this property.
        /// This property is set only by the RealtimeTrace layer.
        /// </summary>
        public string Errors
        {
            get { return this._Errors; }
            set
            {
                if (value == null)
                {
                    value = System.String.Empty;
                }
                this._Errors = value;
            }
        }

        #endregion

        private ThreadManager _tm;


        /// <summary>
        /// Event raises for logging operations.
        /// </summary>
        public event LoggerEventHandler Logger;

        /// <summary>
        /// Handler for logging operations.
        /// </summary>
        /// <param name="message">The message to be logged.</param>
        /// <param name="level">Specifies messages loglevel.</param>
        public void RaiseLogEvent(string message, LogLevel level)
        {
            if (Logger != null)
                Logger(message, level);
        }


        /// <summary>
        /// Returns a dictionary of mounted profiles.
        /// </summary>
        public System.Collections.Generic.Dictionary<char, Profile> MountedDrives
        {
            get
            {
                try
                { return _tm.MountedProfiles; }
                catch (Exception ex)
                {
                    TraceFactory.InsertTrace(this, ex);
                    return null;
                }
            }
            set
            {
            }
        }

        /// <summary>
        /// Mounts a specified profile.
        /// </summary>
        /// <param name="profile">Specifies the profile to be mounted.</param>
        public void MountDrive(Profile profile)
        {
            try
            {
                Logger("MergeFS: Mounting device: " + profile.DriveLetter, LogLevel.debug);
                _tm.MountProfile(profile);
            }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex, profile); throw; }
        }

        /// <summary>
        /// Mounts a specified profile in exclusive mode.
        /// </summary>
        /// <param name="profile">Specifies the profile to be mounted.</param>
        public void MountDriveExclusive(Profile profile)
        {
            try
            { _tm.MountExclusive(profile); }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex, profile); }
        }

        /// <summary>
        /// Unmounts a specified profile.
        /// </summary>
        /// <param name="profile">Specifies the profile to be unmounted.</param>
        public void UnmountDrive(Profile profile)
        {
            try
            {
                Logger("MergeFS: Unmounting device: " + profile.DriveLetter, LogLevel.debug);
                _tm.UnmountProfile(profile);
            }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex, profile); }
        }

        /// <summary>
        /// Unmount all profiles at once.
        /// </summary>
        public void UnmountAll()
        {
            try
            { _tm.UnmountAll(); }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex); }
        }

        /// <summary>
        /// Constructor
        /// </summary>
        public WinMergeFS()
        {
            try
            {
                _tm = new ThreadManager(new LoggerEventHandler(RaiseLogEvent));
                ProfileManager._logger = new LoggerEventHandler(RaiseLogEvent);
            }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex); }
        }

        public static string Version
        {
            get
            {
                return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
            }
            set
            {
            }
        }
    }
}
